package com.zn.znch.yhp.znchv2.service;

import com.alibaba.fastjson.JSONObject;
import com.zn.znch.yhp.znchv2.common.DateUtil;
import com.zn.znch.yhp.znchv2.common.PointDate;
import com.zn.znch.yhp.znchv2.domain.DTO.CCPointData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.fitting.PolynomialCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;
import org.apache.commons.math3.stat.regression.SimpleRegression;

import java.io.*;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

@Slf4j
public class CCTask implements Callable<String> {

    public static int maxLine = 86400;

    private File directory;
    private String name;
    private FileInputStream params;
    private String sysTime;
    private String gsll;
    private String hangzeng;
    private String wenjiang;
    private String chuihuiFlag;
    private Properties properties;

    public CCTask(File directory, String name, FileInputStream params, String sysTime, String gsll, String hangzeng, String wenjiang, String chuihuiFlag, Properties properties){
        this.directory = directory;
        this.name =  name;
        this.params =  params;
        this.sysTime =  sysTime;
        this.gsll =  gsll;
        this.hangzeng =  hangzeng;
        this.wenjiang =  wenjiang;
        this.chuihuiFlag =  chuihuiFlag;
        this.properties = properties;
    }

    @Override
    public String call() throws Exception {

        //如果负荷小于400，则认为是停机状态,则直接返回不需要吹灰
        if(Double.parseDouble(gsll)<400){
            return name+":0";
        }
        List<CCPointData> pointList = readAndWrite(directory, name, params, sysTime, gsll, hangzeng, wenjiang, chuihuiFlag);
        //如果数据小于20000不判断是否吹灰
        if (pointList.size() <= 20000) {
            log.info("当前{}文件总数据量数据不满足20000不进行吹灰判断", name);
            return name+":0";
        }
        //判断是否吹灰
        Boolean flag = chuihuiOpinion(pointList, properties, name);
        //20250224新增最终逻辑判断，限制长吹最短最长吹灰需求出现时间
        int num = zuizhongPanDuan(pointList);
        if(num == 0){
            flag = false;
        }else if(num == 2){
            flag = true;
        }
        String r = flag?"1":"0";
        return name+":"+r;
    }

    private static List<CCPointData> readAndWrite(File directory, String name, FileInputStream params, String sysTime, String gsll, String hangzeng, String wenjiang, String chuihuiFlag) {
        List<CCPointData> list = new ArrayList<>();
        try {
            String filePath = directory.getAbsolutePath() + "/" + name + ".csv";
            File file = new File(filePath);
            List<String> data = new ArrayList<>();
            if (file.exists()) {
                //读取历史数据
                FileReader fr = new FileReader(filePath);
                BufferedReader br = new BufferedReader(fr);
                String line = br.readLine();

                while (line != null) {
                    data.add(line);
                    String[] lineStr = line.split(",");
                    CCPointData pointData = new CCPointData(lineStr[0], Double.parseDouble(lineStr[1]),
                            Double.parseDouble(lineStr[2]), Double.valueOf(lineStr[3]), lineStr[4]);
                    list.add(pointData);
                    line = br.readLine();
                }
                if (data.size() > maxLine) {
                    data.remove(0);
                }
                //删除原文件
                file.delete();
            }
            //重写文件
            FileWriter writer = new FileWriter(filePath);
            for (int i = 0; i < data.size(); i++) {
                writer.append(data.get(i));
                writer.append("\n");
            }
            //新增逻辑：重启机器导致吹灰假象，（倒数第5个数据存在是1天以前的，则设置为吹灰标志设置为_1_1，相当于设置5个吹灰标志）
            CCPointData point = list.get(list.size()-6);
            if(DateUtil.isWithinTenMinutes(point.getTime(), sysTime, 60*24)){
                chuihuiFlag = chuihuiFlag+"_1_1";
            }
            String lineString = sysTime + "," + gsll + "," + hangzeng + "," + wenjiang + "," + chuihuiFlag + "\n";
            writer.append(lineString);
            writer.close();
            log.info(filePath + ":数据更新完成！！");
        } catch (Exception e) {
            log.error("长吹文件处理失败：directory：{}，name：{}，sysTime：{}。错误信息：{}",directory,name,sysTime,e.getMessage());
            e.printStackTrace();
        }
        return list;
    }

    public static Boolean chuihuiOpinion(List<CCPointData> pointDatas, Properties properties, String name) {
        String s = properties.get(name + ".csv").toString();
        String[] param = s.split(",");
        //获取最近一个包含吹灰标记的数据
        CCPointData lastPoint = pointDatas.get(pointDatas.size() - 1);
        if (lastPoint.getChuihui().endsWith("1")) {
            return false;
        }
        int index = 0;
        for (int i = 0; i < pointDatas.size(); i++) {
            CCPointData p = pointDatas.get(i);
            if (p.getChuihui().endsWith("1")) {
                index = i;
            }
        }
        Double a = Double.parseDouble(param[0]);
        Double b = Double.parseDouble(param[1]);
        Double c = Double.parseDouble(param[2]);
        Integer function = Integer.valueOf(param[3]);

        //屏过、末过
        if (!PointDate.wenjiangPoint.keySet().contains(name)) {
            for (int i = index; i < pointDatas.size(); i++) {
                CCPointData beginPoint = pointDatas.get(i);
                double x = beginPoint.getFuhe();
                double lilun = a * x * x + b * x + c;
                double shiji = beginPoint.getZqhz();
                if (shiji < lilun) {
                    boolean f = true;
                    while (f) {
                        i++;
                        if (i >= pointDatas.size() - 1) {
                            return false;
                        }
                        CCPointData next = pointDatas.get(i);
                        double shijiNext = next.getFuhe();
                        double lilunNext = a * shijiNext * shijiNext + b * shijiNext + c ;
                        if (next.getZqhz() > lilunNext) {
                            f = false;
                        }
                        if (next.getZqhz() < lilunNext && DateUtil.isWithinTenMinutes(beginPoint.getTime(), next.getTime(), 3 * 60)) {
//                            String lineString = "当前数据点：[" + JSONObject.toJSONString(next) + "]" + "\n";
//                            wirteChuihuiNote(lineString);
                            log.info("数据点返回吹灰标记，起始时间数据[{}]，当前数据[{}]", JSONObject.toJSONString(beginPoint), JSONObject.toJSONString(next));
                            return true;
                        }
                    }
                }
            }
        } else {
            //检查吹灰后有没有存在理论值>实际值，持续超过4小时的情况，存在则需要吹灰
            for (int i = index; i < pointDatas.size(); i++) {
                CCPointData beginPoint = pointDatas.get(i);
                double x = beginPoint.getFuhe();
                double lilun = a * x * x + b * x + c;
                double shiji = 0d;
                if (function == 1) {
                    shiji = beginPoint.getYqwj();
                } else {
                    shiji = beginPoint.getZqhz() * beginPoint.getFuhe();
                }
                if (shiji < lilun) {
                    //获取到第一个理论值>实际值的点
                    boolean f = true;
                    String beginTime = beginPoint.getTime();
                    while (f) {
                        i++;
                        if (i >= pointDatas.size() - 1) {
                            return false;
                        }
                        CCPointData next = pointDatas.get(i);
                        double x1 = next.getFuhe();
                        double y1 = a * x1 * x1 + b * x1 + c;
                        double shiji1 = 0d;
                        if (function == 1) {
                            shiji1 = next.getYqwj();
                        } else {
                            shiji1 = next.getZqhz() * next.getFuhe();
                        }
                        //持续判断
                        if (shiji1 >= y1) {
                            f = false;
                        }
                        if (shiji1 < y1 && DateUtil.isWithinTenMinutes(beginTime, next.getTime(), 3 * 60)) {
//                            String lineString = "当前数据点：[" + JSONObject.toJSONString(next) + "]" + "\n";
//                            wirteChuihuiNote(lineString);
                            log.info("数据点返回吹灰标记，起始时间数据[{}]，当前数据[{}]", JSONObject.toJSONString(beginPoint), JSONObject.toJSONString(next));
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    //返回0：不能吹，返回1：可以吹，返回2：必须吹
    public int zuizhongPanDuan(List<CCPointData> pointList ){
        HashMap<String,String> map = new HashMap<>();
        CCPointData ccPointData = null;
        for (int i = 0; i < pointList.size(); i++) {
            CCPointData p = pointList.get(i);
            if (p.getChuihui().endsWith("1")) {
                ccPointData = p;
            }
        }

        String bigenTime = ccPointData.getTime();
        if(null == bigenTime){
            return 1;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        LocalDateTime data0 = LocalDateTime.parse(bigenTime, formatter);
        LocalDateTime data1 = LocalDateTime.parse(sysTime, formatter);
        Duration duration = Duration.between(data0, data1);
        long minutes = duration.toMinutes();
        Calendar calendar = Calendar.getInstance();
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int bigen = 0;
        int end = 100000000;
        if(name.equals("HCB11AT001_AM001") || name.equals("HCB12AT001_AM001")){//屏过
            bigen = 60*24*1-dayOfMonth*2;
            end = 60*24*3+dayOfMonth*2;
        }else if(name.equals("HCB11AT002_AM001")  || name.equals("HCB12AT002_AM001")//末过
                || name.equals("HCB11AT003_AM001")  || name.equals("HCB12AT003_AM001") ){//末再
            bigen = 60*24*1-dayOfMonth*2;
            end = 60*24*3+dayOfMonth*2;
//            bigen = 60*4;
//            end = 60*5;
        }else if(name.equals("HCB11AT004_AM001") || name.equals("HCB12AT004_AM001")//低再左\低再右
                || name.equals("HCB11AT005_AM001") || name.equals("HCB12AT005_AM001") ){//低过左\低过右
            bigen = 60*24*7-dayOfMonth*2;
            end = 60*24*8+dayOfMonth*2;
        }else if(name.equals("HCB11AT006_AM001") || name.equals("HCB12AT006_AM001") ){

            bigen = 60*24*3-dayOfMonth*2;
            end = 60*24*4+dayOfMonth*2;
        }
        if(minutes<bigen){
            return 0;
        }
        if(bigen<=minutes && minutes<=end){
            return 1;
        }
        if(end<minutes){
            return 2;
        }
        return 1;
    }
}
